/**
 * &copy; 2006 NewInstance.it
 */
package it.newinstance.jrainbow.converter;

import it.newinstance.jrainbow.parser.java.JavaTag;
import it.newinstance.jrainbow.source.Tag;
import it.newinstance.jrainbow.source.TaggedSource;
import it.newinstance.jrainbow.source.TaggedString;
import it.newinstance.jrainbow.source.TaggedStringIterator;

import java.io.IOException;

/**
 * @author Luigi R. Viggiano
 * @version $Id: JavaToHTMLConverter.java 160 2007-11-15 02:39:42Z luigi.viggiano $
 */
public class JavaToHTMLConverter extends HTMLConverter {

    public JavaToHTMLConverter() {
    }

    public void convert(TaggedSource source) throws IOException {
        if (getWriter() == null) 
            throw new IOException("Output not set for the converter. " +
                    "Please call setWriter method before convert.");
        emitSpanStart(JavaTag.CODE);
        boolean inJavaDoc = false;
        boolean inCommentLine = false;
        boolean inCommentBlock = false;
        for (TaggedString string : new TaggedStringIterator(source)) {
            Tag tag = string.getTag();

            inJavaDoc = fixJavadocBlock(inJavaDoc, tag);
            inCommentLine = fixCommentLine(inCommentLine, tag);
            inCommentBlock = fixCommentBlock(inCommentBlock, tag);

            // special handling for code,javadoc,comment_block, comment_line 
            if (tag != JavaTag.CODE &&  
                tag != JavaTag.JAVADOC &&
                tag != JavaTag.COMMENT_BLOCK &&
                tag != JavaTag.COMMENT_LINE)
                emitSpanStart(tag);

            getWriter().write(htmlEncode(string.getString()));
            
            // special handling for code,javadoc,comment_block, comment_line
            if (tag != JavaTag.CODE && 
                tag != JavaTag.JAVADOC &&
                tag != JavaTag.COMMENT_BLOCK &&
                tag != JavaTag.COMMENT_LINE)                
                emitSpanEnd();
        }
        emitSpanEnd();
    }

    /*
     * Special handling for javadoc
     * (don't emit span everythime)
     */
    private boolean fixJavadocBlock(boolean inJavaDoc, Tag element) 
        throws IOException {
        if (element == JavaTag.JAVADOC
                || element == JavaTag.JAVADOC_KEYWORD                    
                || element == JavaTag.JAVADOC_HTML_TAG
                || element == JavaTag.COMMENT_TASK_TAG) {
            if ((!inJavaDoc) && (element != JavaTag.COMMENT_TASK_TAG)) {
                emitSpanStart(JavaTag.JAVADOC);
                inJavaDoc = true;
            }
        } else if (inJavaDoc) {
            emitSpanEnd();
            inJavaDoc = false;
        }
        return inJavaDoc;
    }

    /*
     * Special handling for comment line
     * (don't emit span every time) 
     */
    private boolean fixCommentLine(boolean inCommentLine, Tag element) 
        throws IOException {
        if (element == JavaTag.COMMENT_LINE
                || element == JavaTag.COMMENT_TASK_TAG) {
            if ((!inCommentLine) && (element != JavaTag.COMMENT_TASK_TAG)) {
                emitSpanStart(JavaTag.COMMENT_LINE);
                inCommentLine = true;
            }
        } else if (inCommentLine) {
            emitSpanEnd();
            inCommentLine = false;
        }
        return inCommentLine;
    }

    /*
     * Special handling for comment block
     * (don't emit span every time) 
     */   
    private boolean fixCommentBlock(boolean inCommentBlock, Tag element) 
        throws IOException {
        if (element == JavaTag.COMMENT_BLOCK
                || element == JavaTag.COMMENT_TASK_TAG) {
            if ((!inCommentBlock) && (element != JavaTag.COMMENT_TASK_TAG)) {
                emitSpanStart(JavaTag.COMMENT_BLOCK);
                inCommentBlock = true;
            }
        } else if (inCommentBlock) {
            emitSpanEnd();
            inCommentBlock = false;
        }
        return inCommentBlock;
    }    
}
